package com.mattgarner.jaddas.node.net;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import com.mattgarner.jaddas.node.ErrorLogManager;
import com.mattgarner.jaddas.node.NodeConfigurationManager;

public class Server implements Runnable {
	private NodeConfigurationManager nodeConfig;
	private ErrorLogManager logManager;
	private ServerSocket serverSocket;
	
	    public Server() {
	    	nodeConfig = NodeConfigurationManager.getInstance();
	    	logManager = ErrorLogManager.getInstance();
	    }
	    
	    // called when this is started as a thread
	    public final void run()  {	
	    	// setup a new listening socket
	        serverSocket = null;
	        try {
	            serverSocket = new ServerSocket(nodeConfig.getListenPort());
	        } catch (IOException e) {
	            logManager.writeToLog(1, "NET", "*** CRITICAL *** Could not bind to listen on port " + nodeConfig.getListenPort() +": " + e.getMessage());
	            System.exit(1);
	        }
	 
	        logManager.writeToLog(4, "NET", "Listening on " +  nodeConfig.getListenPort()+".");
	        
	        Socket clientSocket = null;
	        
	        // wait for incoming connections and launch a new Worker thread to handle it
	        try {  	
	            while((clientSocket = serverSocket.accept()) != null) {
	            	// limit the number of threads we'll handle to prevent overload or DoS
		            if(Worker.getActiveThreadCount() <= nodeConfig.maxConnectionWorkerThreads) {
		            	(new Thread(new Worker(clientSocket))).start();
		            }
	            }
	        } catch (IOException e) {
	        	logManager.writeToLog(1, "NET", "Connection accept failed: " + e.getMessage());
	        }
	        System.out.println("accept wait...");
	    }
	        
	    // we're a daemon so why would we ever close the socket? but just in case...
		private final void closeServerSocket() {
			try { 
				serverSocket.close();
			} catch (IOException e) {
				// nothing;
			}
		}

}
